home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
cool
/
ge_cool.lha
/
GE_COOL2.1
/
src
/
Rational
/
Rational.h
< prev
Wrap
C/C++ Source or Header
|
1992-07-14
|
16KB
|
425 lines
//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated provides this software "as is" without
// express or implied warranty.
//
//
// Created: MBN 10/25/89 -- Initial design and implementation
// Updated: MBN 03/04/90 -- Added execption for DIVIDE_BY_ZERO
// Updated: MJF 07/31/90 -- Added terse print
// Updated: DLS 04/01/91 -- New lite version
//
// The Rational class implements rational numbers and arithmetic. A Rational
// object has the same precision and range of values as the built-in type long.
// Implicit conversion to the system defined types short, int, long, float, and
// double is supported by overloaded operator member functions. Although the
// Rational class makes judicous use of inline functions and deals only with
// integral values, the user is warned that the Rational integer arithmetic
// class is still considerably slower than the built-in integer data types. If
// the range of values anticipated will fit into a built-in type, use that
// instead.
//
// The Rational class implements common arithmetic exception handling and
// provides the application with support for detecting negative infinity,
// positive infinity, overflow, and underflow as a result of some arithmetic
// expression. If one of these conditions or an attempt to convert from a
// Rational with no value to a built-in type is detected, an Error exception is
// raised. The application programmer can provide an exception handler to take
// care of this problem. If no such handler is available, an error message is
// printed and the application terminates.
//
// The Rational class requires several constants be defined to insure precision
// and accuracy of conversion. The preprocessor symbols MINSHORT, MININT,
// MINLONG, MAXSHORT, MAXINT, and MAXLONG are calculated in the <misc.h>
// header file via various bit manipulation macros. The symbols MINFLOAT,
// MINDOUBLE, MAXFLOAT, and MAXDOUBLE are system dependent and cannot be
// calculated. Most systems typically have values for these constants in the
// system header file <values.h>. Values for a specific machine should be
// copied into the <misc.h> header file as necessary.
//
// The private data section of the Rational class contains two long data slots,
// one for the numerator and one for the denominator. The Rational class also
// contains a private data slot providing arithmetic exception status. There
// are five constructors for the Rational class. The first is a simple inline
// constructor that initializes the state and private data slots. The second
// takes two integers (short, int, or long) and uses them as the initial value
// for the object. The second argument is optional and if not supplied,
// defaults to one. The third takes two longs and uses them as the initial
// value for the object. The second argument is optional and if not supplied,
// defaults to one. The fourth takes a double and calculates an equivalent
// normalized rational. Finally, the fifth takes a const reference to another
// Rational object and duplicates its state and value.
//
// The Rational class provides overloaded operators for addition, subtraction,
// multiplication, division, and modulus. Also available are inequality and
// equality, assignment, increment, decrement, unary minus, ones-complement,
// output, less than, greater than, less than or equal, and greater than or
// equal. Methods to get the numerator and denominator, invert, calculate the
// floor and ceiling, truncate, and round are supported. Finally, five type
// conversion functions to short, int, long, float, and double are provided.
#ifndef RATIONAL_H // If no Rational definition
#define RATIONAL_H // define the Rational symbol
#ifndef STREAMH // If the Stream support not yet defined,
#if defined(DOS) || defined(M_XENIX)
#include <stream.hxx> // include the Stream class header file
#else
#include <stream.h> // include the Stream class header file
#endif
#define STREAMH
#endif
#ifndef MISCELANEOUSH // If we have not included this file
#include <misc.h> // Include miscellaneous useful defs
#endif
class CoolRational {
public:
inline CoolRational (); // Simple constructor
CoolRational (long, long d = 1); // Constructor with longs
CoolRational (const CoolRational&); // Copy constructor
inline ~CoolRational(); // destructor
inline long numerator () const; // Get the numerator
inline long denominator () const; // Get the denominator
inline N_status status () const; // Return Number status
inline CoolRational& operator= (const CoolRational&); // Overload assignment
inline Boolean operator== (const CoolRational&) const; // Overload equality
inline Boolean operator!= (const CoolRational&) const; // Overload inequality
inline CoolRational operator-() const; // Unary minus operator
inline Boolean operator!() const; // Unary not operator
CoolRational& operator+= (const CoolRational&); // Overload plus/assign
CoolRational& operator-= (const CoolRational&); // Overload minus/assign
CoolRational& operator*= (const CoolRational&); // Overload multiply/assign
CoolRational& operator/= (const CoolRational&); // Overload divide/assign
CoolRational& operator%= (const CoolRational&); // Overload modulus/assign
inline friend CoolRational operator+ (const CoolRational&, const CoolRational&);
inline friend CoolRational operator- (const CoolRational&, const CoolRational&);
inline friend CoolRational operator* (const CoolRational&, const CoolRational&);
inline friend CoolRational operator/ (const CoolRational&, const CoolRational&);
inline friend CoolRational operator% (const CoolRational&, const CoolRational&);
inline CoolRational& operator++ (); // Overload increment
inline CoolRational& operator-- (); // Overload decrement
Boolean operator< (const CoolRational&) const; // Overload less than
inline Boolean operator<= (const CoolRational&) const; // Overload less/equal
Boolean operator> (const CoolRational&) const; // Overload greater than
inline Boolean operator>= (const CoolRational&) const; // Overload greater/equal
friend ostream& operator<< (ostream&, const CoolRational&); // Output ref
inline friend ostream& operator<< (ostream&, const CoolRational*); // Output ptr
void print(ostream&); // Terse print
CoolRational& invert (); // Invert the rational number
inline long floor () const; // Truncate towards -infinity
inline long ceiling () const; // Truncate towards +infinity
inline long truncate () const; // Truncate towards zero
long round () const; // Truncate to nearest integer
operator short (); // Implicit conversion
operator int (); // Implicit conversion
operator long (); // Implicit conversion
operator float (); // Implicit conversion
inline operator double (); // Implicit conversion
private:
long num; // Numerator portion
long den; // Denominator portion
N_status state; // Exception status
long gcd (long, long); // Calculate GCD
void normalize (); // Normalize num/den
void minus_infinity (const char*) const; // Raise - infinity exception
void plus_infinity (const char*) const; // Raise + infinity exception
void overflow (const char*) const; // Raise overflow error
void underflow (const char*) const; // Raise underflow error
void divide_by_zero (const char*) const; // Raise divide by zero error
};
// Rational -- Simple constructor
// Input: None
// Output: None
inline CoolRational::CoolRational () {
this->num = this->den = 0; // Initialize data slots
this->state = N_OK; // Set status to OK
}
// Rational -- Copy constructor
// Input: Reference to rational object
// Output: None
inline CoolRational::CoolRational (const CoolRational& r) {
this->num = r.num; // Set numerator
this->den = r.den; // Set denominator
this->state = r.state; // Set state
}
// ~Rational -- Destructor does nothing
inline CoolRational::~CoolRational() {}
// numerator -- Return the numerator portion of the rational
// Input: None
// Output: Numerator of rational
inline long CoolRational::numerator () const {
return this->num; // Return numerator
}
// denominator -- Return the denominator portion of the rational
// Input: None
// Output: Denominator of rational
inline long CoolRational::denominator () const {
return this->den; // Return denominator
}
// status -- Return the status of Number
// Input: None
// Output: N_status enum value
inline N_status CoolRational::status () const {
return this->state;
}
// operator= -- Overload the assignment operator for the Rational class
// Input: Reference to rational object
// Output: Reference to updated rational object
inline CoolRational& CoolRational::operator= (const CoolRational& r) {
this->num = r.num; // Set numerator
this->den = r.den; // Set denominator
this->state = r.state; // Set state
return *this; // Return reference
}
// operator== -- Overload the equality operator for the rational class
// Input: Reference to rational object
// Output: TRUE/FALSE
inline Boolean CoolRational::operator== (const CoolRational& r) const {
return (this->num == r.num && this->den == r.den);
}
// operator!= -- Overload the inequality operator for the Rational class
// Input: Reference to a constant rational object
// Ouput: TRUE/FALSE
inline Boolean CoolRational::operator!= (const CoolRational& r) const {
return !(*this == r);
}
// operator< -- Overload operator less than for the rational class
// Input: Reference to rational number
// Output: TRUE/FALSE
inline Boolean CoolRational::operator< (const CoolRational& r) const {
if (this->den == r.den) // If same denominator
return (this->num < r.num); // Return less than sense
else // Else calculate common denom.
return ((this->num * r.den) < (this->den * r.num)); // And return state
}
// operator> -- Overload operator greater than for the rational class
// Input: Reference to rational number
// Output: TRUE/FALSE
inline Boolean CoolRational::operator> (const CoolRational& r) const {
if (this->den == r.den) // If same denominator
return (this->num > r.num); // Return greater than sense
else // Else calculate common denom.
return ((this->num * r.den) > (this->den * r.num)); // And return state
}
// operator<= -- Overload the less than or equal to operator for rational
// Input: Reference to a constant rational object
// Output: TRUE/FALSE
inline Boolean CoolRational::operator<= (const CoolRational& r) const {
return !(*this > r);
}
// operator>= -- Overload the greater than or equal to operator for rational
// Input: Reference to a constant rational object
// Output: TRUE/FALSE
inline Boolean CoolRational::operator>= (const CoolRational& r) const {
return !(*this < r);
}
// operator<< -- Overload the output operator for a reference to a rational
// Input: Reference to an ostream
// Output: Reference to an ostream
inline ostream& operator<< (ostream& os, const CoolRational& r) {
os << r.num << "/" << r.den; // Output rational number
return os; // Return ostream reference
}
// operator<< -- Overload the output operator for a pointer to a rational
// Input: Ostream reference, pointer to a rational object
// Output: Ostream reference
inline ostream& operator<< (ostream& os, const CoolRational* r) {
return operator<< (os, *r);
}
// operator- -- Overload the unary minus operator for the Rational class
// Input: None
// Output: Negated rational value
inline CoolRational CoolRational::operator- () const {
CoolRational r (-this->num, this->den); // Get negative value
return r; // Return deferenced pointer
}
// operator! -- Overload the negation operator for the Rational class
// Input: None
// Output: TRUE/FALSE
inline Boolean CoolRational::operator! () const {
return ((this->num == 0) ? TRUE : FALSE); // Return logical state
}
// operator++ -- Overload the increment operator for the Rational class
// Input: None
// Output: Reference to updated rational object
inline CoolRational& CoolRational::operator++ () {
this->num += this->den; // Increment numerator
return *this; // Return updated object
}
// operator-- -- Overload the decrement operator for the Rational class
// Input: None
// Output: Reference to updated rational object
inline CoolRational& CoolRational::operator-- () {
this->num -= this->den; // Decrement numerator
return *this; // Return updated object
}
// truncate -- Converts rational value by truncating towards zero
// Input: None
// Output: long truncated value
inline long CoolRational::truncate () const {
return (long) (this->num / this->den); // Return truncated rational
}
// floor -- Converts rational value by truncating towards negative infinity
// Input: None
// Output: long value of truncated rational
inline long CoolRational::floor () const {
long temp = this->truncate (); // Get truncated value
return ((this->num < 0.0 && (-(this->num%this->den) > 0.5*this->den)) ?
(temp - 1) : temp);
}
// ceiling -- Converts rational value by truncating towards positive infinity
// Input: None
// Output: long value of truncated rational
inline long CoolRational::ceiling () const {
long temp = this->truncate (); // Get truncated value
return ((this->num > 0.0 && ((this->num%this->den) > 0.5*this->den)) ?
(temp + 1) : temp);
}
// operator+ -- Overload the addition operator for rational
// Input: Reference to two rational numbers
// Output: A new rational number
inline CoolRational operator+ (const CoolRational& r1, const CoolRational& r2) {
CoolRational result(r1);
result += r2;
return result;
}
// operator- -- Overload the subtraction operator for rational
// Input: Reference to two rational numbers
// Output: A new rational number
inline CoolRational operator- (const CoolRational& r1, const CoolRational& r2) {
CoolRational result(r1);
result -= r2;
return result;
}
// operator* -- Overload the multiplication operator for rational
// Input: Reference to two rational numbers
// Output: A new rational number
inline CoolRational operator* (const CoolRational& r1, const CoolRational& r2) {
CoolRational result(r1);
result *= r2;
return result;
}
// operator/ -- Overload the division operator for rational
// Input: Reference to two rational numbers
// Output: A new rational number
inline CoolRational operator/ (const CoolRational& r1, const CoolRational& r2) {
CoolRational result(r1);
result /= r2;
return result;
}
// operator% -- Overload the remainder operator for rational
// Input: Reference to two rational numbers
// Output: A new rational number
inline CoolRational operator% (const CoolRational& r1, const CoolRational& r2) {
CoolRational result(r1);
result %= r2;
return result;
}
// operator double -- Implicit conversion operator from Rational to a double
// Input: None
// Output: Double value equivalent to rational
inline CoolRational::operator double () {
return ((double)this->num)/((double)this->den); // Double answer
}
#endif RATIONAL_H // End RATIONALH